package scan;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;

public class ScanConvert implements Constants{
	Network network;
	
	public ScanConvert(Network network){
		this.network = network;
	}
		

	public HashMap<Integer,HashSet<Integer>> getHashMap(){
		HashMap<Integer,HashSet<Integer>> clustering = new HashMap<Integer,HashSet<Integer>>();
		
		for (Entry<String, Vertex> entry : network.getVertexMap().entrySet()) {

			String vertex_s = entry.getValue().getLabel();
			int clusterID = entry.getValue().getClusterId();
			
			/*
			 * Here should be a error handling, if the vertex_s is not an Integer 
			 */
			if (!clustering.containsKey(clusterID)){
				clustering.put(clusterID, new HashSet<Integer>());
				clustering.get(clusterID).add(new Integer(vertex_s));
			}else{
				clustering.get(clusterID).add(new Integer(vertex_s));
			}

		}
		return clustering;
	}
	public HashMap<Integer,HashSet<Integer>> getFlattenHashMap(HashMap<Integer,HashSet<Integer>> original){
		HashMap<Integer,HashSet<Integer>> flatten = new HashMap<Integer,HashSet<Integer>>();
		
		for (Entry<String, Vertex> entry : network.getVertexMap().entrySet()) {

			String vertex_s = entry.getValue().getLabel();
			int clusterID = entry.getValue().getClusterId();
			
			if (!flatten.containsKey(clusterID)){
				flatten.put(clusterID, new HashSet<Integer>());
				flatten.get(clusterID).addAll(original.get(new Integer(vertex_s)));
			}else{
					flatten.get(clusterID).addAll(original.get(new Integer(vertex_s)));
			}

		}
		return flatten;
	}
	/**
	 * 
	 * @param currentNetHash
	 * @return 
	 * 
	 * This Method returns all clusters that have to be clustered again, because of their size,
	 * given in Constants--> THRESHOLD
	 */
	public HashMap<Integer,Network> innerClusters(){
		HashMap<Integer,HashSet<Integer>> currentNetHash = this.getHashMap();
		/*
		 * iterate over the clusters and create a new Network for all clusters which size
		 * is bigger than THRESHOLD
		 */
		int clusterID;
		HashSet<Integer> cluster;
		HashMap<Integer,Network> nets = new HashMap<Integer,Network>();
		for (Map.Entry<Integer, HashSet<Integer>> entry : currentNetHash.entrySet()) {
			clusterID = entry.getKey();
			cluster = entry.getValue();
			if (cluster.size() > ScanMain.THRESHOLD){
				Network net = new Network(this.network.isDirectedNet(),this.network.isWeightedNet());
				nets.put(clusterID, net);
			}
		}
		/*
		 * Iterate over all edges of the clustered network. Add a new edge where VertexA.clusterID ==
		 * VertexB.clusterID. And the clusterID is part of a cluster that has (size > THRESHOLD)
		 */
		String a_s,b_s;
		Edge edge;
		int clusterID_A,clusterID_B;
		double weight = 1.0;
		for (Entry<Integer, Edge> entry : network.getEdgeMap().entrySet()) {
			edge = entry.getValue();
			a_s = edge.getVertexA();
			b_s = edge.getVertexB();
			clusterID_A = network.getVertexMap().get(a_s).getClusterId();
			clusterID_B = network.getVertexMap().get(b_s).getClusterId();
			if ((clusterID_A == clusterID_B) && nets.containsKey(clusterID_A)){
				nets.get(clusterID_A).addEdge(a_s, b_s, weight);
			}
		}
		return nets;
	}


	public Network getFlattenNetwork(Network currentNet) {
		String vertex_s;
		int x;
		int clusterID,clusterIDNew;
		for (Entry<String, Vertex> entry : network.getVertexMap().entrySet()) {

			vertex_s = entry.getValue().getLabel();
			clusterID = entry.getValue().getClusterId();
			 
			
			if(currentNet.getVertexMap().containsKey(Integer.toString(clusterID))){
				clusterIDNew = currentNet.getVertexMap().get(Integer.toString(clusterID)).getClusterId();
				network.getVertexMap().get(vertex_s).setClusterId(clusterIDNew);
			}
//			else{
//				network.getVertexMap().get(vertex_s).setClusterId(-99);
//			}

		}
		return null;
	}

}

